package com.ehouse.widgets;

import java.util.ArrayList;
import java.util.Arrays;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.database.Cursor;
import android.net.Uri;
import android.preference.PreferenceManager;
import android.support.v4.content.CursorLoader;
import android.support.v4.content.Loader;
import android.support.v4.content.Loader.OnLoadCompleteListener;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

import com.ehouse.R;
import com.ehouse.connection.ConnectionService;
import com.ehouse.connection.ConnectionService.IConnectionResponseListener;
import com.ehouse.database.TemperatureTable;
import com.ehouse.models.Settings;

public class TemperatureWidget extends AppWidgetProvider {

	private static final String LOG_TAG = "TemperatureWidget";
	private static final String ACTION_TAG = "ACTION";
	private static Context gContext;

	@Override
	public void onUpdate(final Context context, AppWidgetManager appWidgetManager,
			int[] appWidgetIds) {
		gContext = context;
		Log.d(LOG_TAG, "onUpdate ids: " + Arrays.toString(appWidgetIds));

		final int n = appWidgetIds.length;
		for (int i = 0; i < n; i++) {
			final int appWidgetId = appWidgetIds[i];

			Uri data = Uri.withAppendedPath(Uri.parse("heat://widget/id/"),
					String.valueOf(appWidgetId));
			Intent heatIntent = new Intent(context, TemperatureUpdater.class);
			heatIntent.setData(data);
			heatIntent.putExtra(ACTION_TAG, 1);

			data = Uri.withAppendedPath(Uri.parse("ac://widget/id/"),
					String.valueOf(appWidgetId));
			Intent acIntent = new Intent(context, TemperatureUpdater.class);
			acIntent.setData(data);
			acIntent.putExtra(ACTION_TAG, 0);

			PendingIntent heat = PendingIntent.getBroadcast(context, 0,
					heatIntent, PendingIntent.FLAG_UPDATE_CURRENT);
			PendingIntent ac = PendingIntent.getBroadcast(context, 0, acIntent,
					PendingIntent.FLAG_UPDATE_CURRENT);

			loadData(context);
			
			RemoteViews rv = new RemoteViews(context.getPackageName(),
					R.layout.temperature_widget);
			rv.setOnClickPendingIntent(R.id.heat, heat);
			rv.setOnClickPendingIntent(R.id.cold, ac);

			ComponentName thisWidget = new ComponentName(context,
					TemperatureWidget.class);
			AppWidgetManager manager = AppWidgetManager.getInstance(context);
			manager.updateAppWidget(thisWidget, rv);
		}
	}
	
	private void loadData(final Context context) {
		final Loader<Cursor> cl = new CursorLoader(context, TemperatureTable.CONTENT_URI, new String[]{TemperatureTable.COLUMN_TEMP, TemperatureTable.COLUMN_STATE_H, TemperatureTable.COLUMN_STATE_A}, null, null, null);
		cl.registerListener(cl.getId(), new OnLoadCompleteListener<Cursor>() {

			public void onLoadComplete(Loader<Cursor> loader, Cursor data) {
				Log.d(LOG_TAG, "Data load complete in loadData");
				boolean cont = data.moveToFirst();
				while (cont) {
					Log.d(LOG_TAG, "Processing row...");
					final double temp = data.getDouble(data.getColumnIndex(TemperatureTable.COLUMN_TEMP));
					final int state_h = data.getInt(data.getColumnIndex(TemperatureTable.COLUMN_STATE_H));
					final int state_a = data.getInt(data.getColumnIndex(TemperatureTable.COLUMN_STATE_A));
					
					Log.d(LOG_TAG, "Temperature: " + temp);
					Log.d(LOG_TAG, "Heating value: " + state_h);
					Log.d(LOG_TAG, "A/C value: " + state_a);
					
					changeTemperature(context, getTempString(context, temp));
					changeIcon(context, R.id.heat, state_h == 0 ? R.drawable.heat_off : R.drawable.heat_on);
					changeIcon(context, R.id.cold, state_a == 0 ? R.drawable.cold_off : R.drawable.cold_on);
					
					cont = data.moveToNext();
				}
				cl.unregisterListener(this);
			}
		});
		cl.startLoading();
	}

	private static void changeIcon(Context context, int resToChange, int newIcon) {
		RemoteViews rv = new RemoteViews(context.getPackageName(),
				R.layout.temperature_widget);
		rv.setImageViewResource(resToChange, newIcon);
		ComponentName thisWidget = new ComponentName(context,
				TemperatureWidget.class);
		AppWidgetManager manager = AppWidgetManager.getInstance(context);
		manager.updateAppWidget(thisWidget, rv);
	}
	
	private static void changeTemperature(Context context, String tempString) {
		RemoteViews rv = new RemoteViews(context.getPackageName(),
				R.layout.temperature_widget);
		rv.setTextViewText(R.id.temperature, tempString);
		ComponentName thisWidget = new ComponentName(context,
				TemperatureWidget.class);
		AppWidgetManager manager = AppWidgetManager.getInstance(context);
		manager.updateAppWidget(thisWidget, rv);
	}
	
	public static String getTempString(Context context, double temp) {
		SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(context);
		boolean fahrenheit = (sharedPrefs.getString(Settings.TEMP_UNIT, "0").equals("1"));
		String unit = context.getResources().getString(R.string.unit_c);
		if (fahrenheit) {
			temp = (((temp / 5) * 9) + 32);
			unit = context.getResources().getString(R.string.unit_f);
		}
		return temp + unit;
	}
	
	private static IConnectionResponseListener createListener(
			final int resToChange,
			final int onIcon, final int offIcon, final int state,
			final int otherRes, final int otherOff, final boolean change) {
		IConnectionResponseListener listener = new IConnectionResponseListener() {
			
			private static final long serialVersionUID = -6474678486696268936L;
			
			public void responseReceived(Object data2, boolean success) {
				Log.d(LOG_TAG, "Socket communication finished received");
				if (!success) {
					Toast.makeText(gContext, R.string.IO_exception, Toast.LENGTH_LONG).show();
				} else {
					changeIcon(gContext, resToChange, state == 0 ? onIcon : offIcon);
					if (change) {
						changeIcon(gContext, otherRes, otherOff);
					}
				}
			}
		};
		return listener;
	}

	public static class TemperatureUpdater extends BroadcastReceiver {

		public TemperatureUpdater() {
			super();
		}

		@Override
		public void onReceive(Context context, Intent intent) {
			int action = intent.getExtras().getInt(ACTION_TAG, -1);
			Log.d(LOG_TAG, "Handled intent with action " + action);
			if (action == 1) {
				Log.d(LOG_TAG, "Toggle heat");
				toggle(context, TemperatureTable.COLUMN_STATE_H, TemperatureTable.COLUMN_LABEL_H, R.id.heat, R.drawable.heat_on, R.drawable.heat_off, R.id.cold, TemperatureTable.COLUMN_LABEL_A, R.drawable.cold_off);
			} else if (action == 0) {
				Log.d(LOG_TAG, "Toggle A/C");
				toggle(context, TemperatureTable.COLUMN_STATE_A, TemperatureTable.COLUMN_LABEL_A, R.id.cold, R.drawable.cold_on, R.drawable.cold_off, R.id.heat, TemperatureTable.COLUMN_LABEL_H, R.drawable.heat_off);
			}
		}
		
		private void toggle(final Context context, final String stateCol, final String switchNameCol, final int resToChange, final int onIcon, final int offIcon, final int otherRes, final String otherSwitchName, final int otherOff) {
			final Loader<Cursor> cl = new CursorLoader(context, TemperatureTable.CONTENT_URI, new String[]{TemperatureTable.COLUMN_TEMP, stateCol, switchNameCol, otherSwitchName}, null, null, null);
			cl.registerListener(cl.getId(), new OnLoadCompleteListener<Cursor>() {

				public void onLoadComplete(Loader<Cursor> loader, final Cursor data) {
					Log.d(LOG_TAG, "Data load complete in toggle. Rows: " + data.getCount());
					boolean cont = data.moveToFirst();
					while (cont) {
						Log.d(LOG_TAG, "Processing row...");
						final double temp = data.getDouble(data.getColumnIndex(TemperatureTable.COLUMN_TEMP));
						final int state = data.getInt(data.getColumnIndex(stateCol));
						final String name = data.getString(data.getColumnIndex(switchNameCol));
						final String otherName = data.getString(data.getColumnIndex(otherSwitchName));
						changeTemperature(context, getTempString(context, temp));

						IConnectionResponseListener listener = createListener(
								resToChange, onIcon, offIcon, state, otherRes, otherOff, state == 0);

						Intent bindIntent = new Intent(context, ConnectionService.class);
						bindIntent.putExtra(ConnectionService.WIDGET_CALL_IP,
								PreferenceManager.getDefaultSharedPreferences(context).getString(Settings.IP, null));
						bindIntent.putExtra(ConnectionService.WIDGET_SWITCH_SENSOR, "Temperature");
						ArrayList<String> names = new ArrayList<String>(2);
						names.add(name);
						names.add(otherName);
						bindIntent.putStringArrayListExtra(ConnectionService.WIDGET_SWITCH_SENSOR_NAME, names);
						bindIntent.putExtra(ConnectionService.WIDGET_SWITCH_SENSOR_STATE, state == 0);
						bindIntent.putExtra(ConnectionService.WIDGET_SWITCH_SENSOR_LISTENER, (java.io.Serializable) listener);
						bindIntent.putExtra(ConnectionService.WIDGET_SELECTION, ConnectionService.TEMP_WIDGET);
						context.startService(bindIntent);
						
						cont = data.moveToNext();
					}
					cl.unregisterListener(this);
				}
			});
			cl.startLoading();
		}

	}

}
